package com.cyzy.homework.service.impl;

import com.cyzy.homework.dto.UserDTO;
import com.cyzy.homework.entity.LeaveRequest;
import com.cyzy.homework.entity.User;
import com.cyzy.homework.repository.LeaveRequestRepository;
import com.cyzy.homework.repository.UserRepository;
import com.cyzy.homework.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 用户服务实现类
 */
@Service
@Transactional
public class UserServiceImpl implements UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private LeaveRequestRepository leaveRequestRepository;
    
    private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    
    @Override
    public UserDTO getUserById(Integer id) {
        Optional<User> userOpt = userRepository.findById(id);
        if (!userOpt.isPresent()) {
            throw new RuntimeException("用户不存在");
        }
        
        User user = userOpt.get();
        UserDTO userDTO = convertToDTO(user);
        
        // 设置健康码信息
        setHealthCodeInfo(userDTO);
        
        return userDTO;
    }
    
    @Override
    public UserDTO getUserByUsername(Integer username) {
        Optional<User> userOpt = userRepository.findByUsername(username);
        if (!userOpt.isPresent()) {
            throw new RuntimeException("用户不存在");
        }
        
        User user = userOpt.get();
        UserDTO userDTO = convertToDTO(user);
        
        // 设置健康码信息
        setHealthCodeInfo(userDTO);
        
        return userDTO;
    }
    
    @Override
    public Page<UserDTO> getAllUsers(Pageable pageable) {
        Page<User> users = userRepository.findAll(pageable);
        return users.map(user -> {
            UserDTO userDTO = convertToDTO(user);
            setHealthCodeInfo(userDTO);
            return userDTO;
        });
    }
    
    @Override
    public List<UserDTO> getUsersByRole(Integer role) {
        List<User> users = userRepository.findByRole(role);
        return users.stream().map(user -> {
            UserDTO userDTO = convertToDTO(user);
            setHealthCodeInfo(userDTO);
            return userDTO;
        }).collect(Collectors.toList());
    }
    
    @Override
    public List<UserDTO> getStudentsByClassId(Integer classId) {
        List<User> students = userRepository.findStudentsByClassId(classId);
        return students.stream().map(user -> {
            UserDTO userDTO = convertToDTO(user);
            setHealthCodeInfo(userDTO);
            return userDTO;
        }).collect(Collectors.toList());
    }
    
    @Override
    public List<UserDTO> getUsersByClassId(Integer classId) {
        // 查找所有角色的用户
        List<User> students = userRepository.findByRoleAndClassId(0, classId);
        List<User> teachers = userRepository.findByRoleAndClassId(1, classId);
        
        List<User> allUsers = new java.util.ArrayList<>();
        allUsers.addAll(students);
        allUsers.addAll(teachers);
        
        return allUsers.stream().map(user -> {
            UserDTO userDTO = convertToDTO(user);
            setHealthCodeInfo(userDTO);
            return userDTO;
        }).collect(Collectors.toList());
    }
    
    @Override
    public List<UserDTO> getAllTeachers() {
        List<User> teachers = userRepository.findAllTeachers();
        return teachers.stream().map(user -> {
            UserDTO userDTO = convertToDTO(user);
            setHealthCodeInfo(userDTO);
            return userDTO;
        }).collect(Collectors.toList());
    }
    
    @Override
    public List<UserDTO> getAllStudents() {
        List<User> students = userRepository.findAllStudents();
        return students.stream().map(user -> {
            UserDTO userDTO = convertToDTO(user);
            setHealthCodeInfo(userDTO);
            return userDTO;
        }).collect(Collectors.toList());
    }
    
    @Override
    public UserDTO updateUserProfile(Integer id, UserDTO userDTO) {
        Optional<User> userOpt = userRepository.findById(id);
        if (!userOpt.isPresent()) {
            throw new RuntimeException("用户不存在");
        }
        
        User user = userOpt.get();
        
        // 更新允许修改的字段
        if (userDTO.getNickname() != null) {
            user.setNickname(userDTO.getNickname());
        }
        if (userDTO.getAvatar() != null) {
            user.setAvatar(userDTO.getAvatar());
        }
        if (userDTO.getGender() != null) {
            user.setGender(userDTO.getGender());
        }
        if (userDTO.getAge() != null) {
            user.setAge(userDTO.getAge());
        }
        if (userDTO.getPhone() != null) {
            user.setPhone(userDTO.getPhone());
        }
        
        user = userRepository.save(user);
        UserDTO result = convertToDTO(user);
        setHealthCodeInfo(result);
        
        return result;
    }
    
    @Override
    public UserDTO getUserHealthCode(Integer id) {
        UserDTO userDTO = getUserById(id);
        return userDTO; // 健康码信息已在getUserById中设置
    }
    
    @Override
    public boolean userExists(Integer username) {
        return userRepository.existsByUsername(username);
    }
    
    @Override
    public UserDTO login(Integer username, String password) {
        Optional<User> userOpt = userRepository.findByUsername(username);
        if (!userOpt.isPresent()) {
            throw new RuntimeException("用户名或密码错误");
        }
        
        User user = userOpt.get();
        
        // 验证密码
        if (!passwordEncoder.matches(password, user.getPassword())) {
            throw new RuntimeException("用户名或密码错误");
        }
        
        UserDTO userDTO = convertToDTO(user);
        setHealthCodeInfo(userDTO);
        
        return userDTO;
    }
    
    @Override
    public UserDTO register(UserDTO userDTO, String password) {
        // 检查用户名是否已存在
        if (userRepository.existsByUsername(userDTO.getUsername())) {
            throw new RuntimeException("用户名已存在");
        }
        
        // 检查手机号是否已存在
        if (userDTO.getPhone() != null && userRepository.existsByPhone(userDTO.getPhone())) {
            throw new RuntimeException("手机号已注册");
        }
        
        User user = new User();
        BeanUtils.copyProperties(userDTO, user);
        
        // 加密密码
        user.setPassword(passwordEncoder.encode(password));
        
        user = userRepository.save(user);
        UserDTO result = convertToDTO(user);
        setHealthCodeInfo(result);
        
        return result;
    }
    
    /**
     * 设置用户健康码信息
     */
    private void setHealthCodeInfo(UserDTO userDTO) {
        LocalDate currentDate = LocalDate.now();
        Optional<LeaveRequest> currentLeave = leaveRequestRepository
            .findCurrentActiveLeaveByUserId(userDTO.getId().toString(), currentDate);
        
        if (currentLeave.isPresent()) {
            LeaveRequest leave = currentLeave.get();
            userDTO.setOnLeave(true);
            
            // 根据请假类型设置健康码状态
            if (leave.getLeaveType() == 1) { // 病假/健康请假
                userDTO.setHealthCodeStatus(2); // 红码
                userDTO.setHealthCodeMessage("健康请假中，请注意休息");
            } else { // 事假
                userDTO.setHealthCodeStatus(1); // 黄码
                userDTO.setHealthCodeMessage("请假中");
            }
            
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            userDTO.setCurrentLeaveInfo(String.format("请假时间：%s 至 %s，原因：%s", 
                leave.getStartDate().format(formatter),
                leave.getEndDate().format(formatter),
                leave.getReason()));
        } else {
            userDTO.setOnLeave(false);
            userDTO.setHealthCodeStatus(0); // 绿码
            userDTO.setHealthCodeMessage("健康正常");
            userDTO.setCurrentLeaveInfo(null);
        }
    }
    
    /**
     * 转换为DTO
     */
    private UserDTO convertToDTO(User user) {
        UserDTO dto = new UserDTO();
        BeanUtils.copyProperties(user, dto);
        return dto;
    }
}
